package com.e0box.game.utils.storage
{
	import flash.display.BitmapData;
	import flash.geom.Matrix;
	
	import utils.ObjectArray;

	/**
	 * single instance
	 * storage all BitmapData instance.
	 * 
	 * @author AgCO
	 * 
	 */	
	public class BitmapDataStorage
	{	
		protected static var _instance:BitmapDataStorage;
		/**
		 * the storage(ObjectArr).
		 */		
		protected var _storage:ObjectArray;
		/**
		 * the storage(ObjectArr) of flipped BitmapData.
		 */	
		protected var _flipped:ObjectArray;
		
		/**
		 * use class 'validate' whitch outside package.
		 * 
		 * @param single
		 * 
		 */		
		public function BitmapDataStorage(single:validate)
		{
			if(!single){
				throw new Error("Please use the static method 'get instance'.");
			}
			init();
		}
		/**
		 * init
		 * 
		 */		
		private function init():void{
			_storage=new ObjectArray();
			_flipped=new ObjectArray();
		}
		
		/**
		 * getter the storage ObjectArray.
		 * don't use it
		 * 
		 * @return 
		 * 
		 */		
		public function get storage():ObjectArray{
			return _storage;
		}
		/**
		 * put BitmapData in storage with the key
		 * 
		 * @param key
		 * @param value
		 * 
		 */		
		public function put(key:String,value:BitmapData,createFlip:Boolean=false):void{
			_storage.put(key,value);
			if(createFlip){
				createFlipped(key);
			}
		}
		/**
		 * get BitmapData by key
		 * return null if storage don't contain this key
		 * @param key
		 * @return 
		 * 
		 */		
		public function getBitmapByKey(key:String):BitmapData{
			return _storage.getValueByKey(key) as BitmapData;
		}
		/**
		 * get flipped BitmapData by key
		 * @param key
		 * @return 
		 * 
		 */		
		public function getFlippedByKey(key:String):BitmapData{
			if(!_flipped.containsKey(key)){
				createFlipped(key);
			}
			return _flipped.getValueByKey(key) as BitmapData;
		}
		/**
		 * create flipped BitmapData by key
		 * @param key
		 * 
		 */		
		public function createFlipped(key:String):void{
			if(_flipped.containsKey(key)) return;
			var source:BitmapData=getBitmapByKey(key);
			if(!source){
				throw new Error("There is no key '"+key+"' in storage.");
			}
			var data:BitmapData=new BitmapData(source.width,source.height,true,0);
			var matrix:Matrix=new Matrix();
			matrix.a=-1;
			matrix.tx=data.width;
			data.draw(source,matrix);
			_flipped.put(key,data);
		}
		/**
		 * getter count of storage
		 * @return 
		 * 
		 */		
		public function get size():uint{
			return _storage.size;
		}
		/**
		 * clear the storage.dispose all of the BitmapData
		 * 
		 */		
		public function clear():void{
			var keys:Vector.<String>=getKeys();
			var key:String;
			while(keys.length){
				removeByKey(keys.pop());
			}
		}
		/**
		 * check storage contain the key
		 * 
		 * @param key
		 * @return 
		 * 
		 */		
		public function containsKey(key:String):Boolean{
			return _storage.containsKey(key);
		}
		/**
		 * remove & dispose BitmapData by key
		 * @param key
		 * @return 
		 * 
		 */		
		public function removeByKey(key:String):Boolean{
			if(_storage.containsKey(key)){
				(_storage.getValueByKey(key) as BitmapData).dispose();
				if(_flipped.containsKey(key)){
					(_flipped.getValueByKey(key) as BitmapData).dispose();
					_flipped.removeByKey(key);
				}
				return _storage.removeByKey(key);
			}
			return false;
		}
		/**
		 * get all of storage keys
		 * 
		 * @return 
		 * 
		 */		
		public function getKeys():Vector.<String>{
			var result:Vector.<String>=Vector.<String>(_storage.getKeys());
			
			return result;
		}
		/**
		 * get all of storage BitmapDatas
		 * @return 
		 * 
		 */		
		public function getValues():Vector.<BitmapData>{
			var result:Vector.<BitmapData>=Vector.<BitmapData>(_storage.getValues());
			
			return result;
		}
		
		/**
		 * only way to get instance of this class.
		 * @return 
		 * 
		 */		
		public static function get instance():BitmapDataStorage{
			if(!_instance){
				_instance=new BitmapDataStorage(new validate());
			}
			return _instance;
		}
	}
}
class validate{
	public function validate(){
		
	}
}